﻿using Core.SimpleTemp.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Core.Toolkit.PagingQuery
{

    public static class OderyHelp
    {
        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="Field"></param>
        /// <param name="orderby"></param>
        /// <returns></returns>
        public static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> query, string propertyName, bool IsDesc, bool isFirstOrder)
        {
            if (!string.IsNullOrEmpty(propertyName))
            {
                var propInfo = GetPropertyInfo(typeof(T), propertyName);
                var expr = GetOrderExpression(typeof(T), propertyName);

                if (!IsDesc)
                {
                    var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (isFirstOrder ? "OrderBy" : "ThenBy") && m.GetParameters().Length == 2);
                    var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
                    return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
                }
                else
                {
                    var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == (isFirstOrder ? "OrderByDescending" : "ThenByDescending") && m.GetParameters().Length == 2);
                    var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
                    return (IOrderedQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
                }
            }
            return null;
        }

        /// <summary>
        /// 获取反射
        /// </summary>
        /// <param name="objType"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private static PropertyInfo GetPropertyInfo(Type objType, string propertyName)
        {
            Type type = null;
            //分割属性
            var conlumnLevel = propertyName.Split('.');
            int i = 0;
            PropertyInfo curr = null;
            foreach (var item in conlumnLevel)
            {
                if (i == 0)
                {

                    curr = objType.GetProperties().FirstOrDefault(p => p.Name == item);
                }
                else
                    curr = type.GetProperties().FirstOrDefault(p => p.Name == item);
                type = curr.PropertyType;
                i++;
            }
            return curr;
        }

        /// <summary>
        /// 获取生成表达式
        /// </summary>
        /// <param name="objType"></param>
        /// <param name="pi"></param>
        /// <returns></returns>
        private static LambdaExpression GetOrderExpression(Type objType, string propertyName)
        {
            var parameter = Expression.Parameter(objType, "p");//创建参数i
            var exp = ExpressionExtension.GetParameter(parameter, propertyName);
            var expr = Expression.Lambda(exp, parameter);
            return expr;
        }
    }
}
